
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>django.utils.cache &#8212; Django 1.11.22.dev20190603194737 documentation</title>
    <link rel="stylesheet" href="../../../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
    <script type="text/javascript" id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../../../_static/jquery.js"></script>
    <script type="text/javascript" src="../../../_static/underscore.js"></script>
    <script type="text/javascript" src="../../../_static/doctools.js"></script>
    <script type="text/javascript" src="../../../_static/language_data.js"></script>
    <link rel="index" title="Index" href="../../../genindex.html" />
    <link rel="search" title="Search" href="../../../search.html" />



 
<script type="text/javascript" src="../../../templatebuiltins.js"></script>
<script type="text/javascript">
(function($) {
    if (!django_template_builtins) {
       // templatebuiltins.js missing, do nothing.
       return;
    }
    $(document).ready(function() {
        // Hyperlink Django template tags and filters
        var base = "../../../ref/templates/builtins.html";
        if (base == "#") {
            // Special case for builtins.html itself
            base = "";
        }
        // Tags are keywords, class '.k'
        $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
             var tagname = $(elem).text();
             if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
                 var fragment = tagname.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
             }
        });
        // Filters are functions, class '.nf'
        $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
             var filtername = $(elem).text();
             if ($.inArray(filtername, django_template_builtins.tfilters) != -1) {
                 var fragment = filtername.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>");
             }
        });
    });
})(jQuery);
</script>


  </head><body>

    <div class="document">
  <div id="custom-doc" class="yui-t6">
    <div id="hd">
      <h1><a href="../../../index.html">Django 1.11.22.dev20190603194737 documentation</a></h1>
      <div id="global-nav">
        <a title="Home page" href="../../../index.html">Home</a>  |
        <a title="Table of contents" href="../../../contents.html">Table of contents</a>  |
        <a title="Global index" href="../../../genindex.html">Index</a>  |
        <a title="Module index" href="../../../py-modindex.html">Modules</a>
      </div>
      <div class="nav">
    <a href="../../index.html" title="Module code" accesskey="U">up</a></div>
    </div>

    <div id="bd">
      <div id="yui-main">
        <div class="yui-b">
          <div class="yui-g" id="_modules-django-utils-cache">
            
  <h1>Source code for django.utils.cache</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">This module contains helper functions for controlling caching. It does so by</span>
<span class="sd">managing the &quot;Vary&quot; header of responses. It includes functions to patch the</span>
<span class="sd">header of response objects directly and decorators that change functions to do</span>
<span class="sd">that header-patching themselves.</span>

<span class="sd">For information on the Vary header, see:</span>

<span class="sd">    https://tools.ietf.org/html/rfc7231#section-7.1.4</span>

<span class="sd">Essentially, the &quot;Vary&quot; HTTP header defines which headers a cache should take</span>
<span class="sd">into account when building its cache key. Requests with the same path but</span>
<span class="sd">different header content for headers named in &quot;Vary&quot; need to get different</span>
<span class="sd">cache keys to prevent delivery of wrong content.</span>

<span class="sd">An example: i18n middleware would need to distinguish caches by the</span>
<span class="sd">&quot;Accept-language&quot; header.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="k">import</span> <span class="n">unicode_literals</span>

<span class="kn">import</span> <span class="nn">hashlib</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">warnings</span>

<span class="kn">from</span> <span class="nn">django.conf</span> <span class="k">import</span> <span class="n">settings</span>
<span class="kn">from</span> <span class="nn">django.core.cache</span> <span class="k">import</span> <span class="n">caches</span>
<span class="kn">from</span> <span class="nn">django.http</span> <span class="k">import</span> <span class="n">HttpResponse</span><span class="p">,</span> <span class="n">HttpResponseNotModified</span>
<span class="kn">from</span> <span class="nn">django.utils.deprecation</span> <span class="k">import</span> <span class="n">RemovedInDjango21Warning</span>
<span class="kn">from</span> <span class="nn">django.utils.encoding</span> <span class="k">import</span> <span class="n">force_bytes</span><span class="p">,</span> <span class="n">force_text</span><span class="p">,</span> <span class="n">iri_to_uri</span>
<span class="kn">from</span> <span class="nn">django.utils.http</span> <span class="k">import</span> <span class="p">(</span>
    <span class="n">http_date</span><span class="p">,</span> <span class="n">parse_etags</span><span class="p">,</span> <span class="n">parse_http_date_safe</span><span class="p">,</span> <span class="n">quote_etag</span><span class="p">,</span>
<span class="p">)</span>
<span class="kn">from</span> <span class="nn">django.utils.timezone</span> <span class="k">import</span> <span class="n">get_current_timezone_name</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="k">import</span> <span class="n">get_language</span>

<span class="n">cc_delim_re</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\s*,\s*&#39;</span><span class="p">)</span>

<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">&#39;django.request&#39;</span><span class="p">)</span>


<div class="viewcode-block" id="patch_cache_control"><a class="viewcode-back" href="../../../ref/utils.html#django.utils.cache.patch_cache_control">[docs]</a><span class="k">def</span> <span class="nf">patch_cache_control</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    This function patches the Cache-Control header by adding all</span>
<span class="sd">    keyword arguments to it. The transformation is as follows:</span>

<span class="sd">    * All keyword parameter names are turned to lowercase, and underscores</span>
<span class="sd">      are converted to hyphens.</span>
<span class="sd">    * If the value of a parameter is True (exactly True, not just a</span>
<span class="sd">      true value), only the parameter name is added to the header.</span>
<span class="sd">    * All other parameters are added with their value, after applying</span>
<span class="sd">      str() to it.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">def</span> <span class="nf">dictitem</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
        <span class="n">t</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;=&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">t</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
            <span class="k">return</span> <span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> <span class="kc">True</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">dictvalue</span><span class="p">(</span><span class="n">t</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">True</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1">=</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>

    <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;Cache-Control&#39;</span><span class="p">):</span>
        <span class="n">cc</span> <span class="o">=</span> <span class="n">cc_delim_re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">response</span><span class="p">[</span><span class="s1">&#39;Cache-Control&#39;</span><span class="p">])</span>
        <span class="n">cc</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">dictitem</span><span class="p">(</span><span class="n">el</span><span class="p">)</span> <span class="k">for</span> <span class="n">el</span> <span class="ow">in</span> <span class="n">cc</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">cc</span> <span class="o">=</span> <span class="p">{}</span>

    <span class="c1"># If there&#39;s already a max-age header but we&#39;re being asked to set a new</span>
    <span class="c1"># max-age, use the minimum of the two ages. In practice this happens when</span>
    <span class="c1"># a decorator and a piece of middleware both operate on a given view.</span>
    <span class="k">if</span> <span class="s1">&#39;max-age&#39;</span> <span class="ow">in</span> <span class="n">cc</span> <span class="ow">and</span> <span class="s1">&#39;max_age&#39;</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">:</span>
        <span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;max_age&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">cc</span><span class="p">[</span><span class="s1">&#39;max-age&#39;</span><span class="p">]),</span> <span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;max_age&#39;</span><span class="p">])</span>

    <span class="c1"># Allow overriding private caching and vice versa</span>
    <span class="k">if</span> <span class="s1">&#39;private&#39;</span> <span class="ow">in</span> <span class="n">cc</span> <span class="ow">and</span> <span class="s1">&#39;public&#39;</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">:</span>
        <span class="k">del</span> <span class="n">cc</span><span class="p">[</span><span class="s1">&#39;private&#39;</span><span class="p">]</span>
    <span class="k">elif</span> <span class="s1">&#39;public&#39;</span> <span class="ow">in</span> <span class="n">cc</span> <span class="ow">and</span> <span class="s1">&#39;private&#39;</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">:</span>
        <span class="k">del</span> <span class="n">cc</span><span class="p">[</span><span class="s1">&#39;public&#39;</span><span class="p">]</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
        <span class="n">cc</span><span class="p">[</span><span class="n">k</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">&#39;_&#39;</span><span class="p">,</span> <span class="s1">&#39;-&#39;</span><span class="p">)]</span> <span class="o">=</span> <span class="n">v</span>
    <span class="n">cc</span> <span class="o">=</span> <span class="s1">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">dictvalue</span><span class="p">(</span><span class="n">el</span><span class="p">)</span> <span class="k">for</span> <span class="n">el</span> <span class="ow">in</span> <span class="n">cc</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
    <span class="n">response</span><span class="p">[</span><span class="s1">&#39;Cache-Control&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">cc</span></div>


<div class="viewcode-block" id="get_max_age"><a class="viewcode-back" href="../../../ref/utils.html#django.utils.cache.get_max_age">[docs]</a><span class="k">def</span> <span class="nf">get_max_age</span><span class="p">(</span><span class="n">response</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Returns the max-age from the response Cache-Control header as an integer</span>
<span class="sd">    (or ``None`` if it wasn&#39;t found or wasn&#39;t an integer.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">has_header</span><span class="p">(</span><span class="s1">&#39;Cache-Control&#39;</span><span class="p">):</span>
        <span class="k">return</span>
    <span class="n">cc</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">_to_tuple</span><span class="p">(</span><span class="n">el</span><span class="p">)</span> <span class="k">for</span> <span class="n">el</span> <span class="ow">in</span> <span class="n">cc_delim_re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">response</span><span class="p">[</span><span class="s1">&#39;Cache-Control&#39;</span><span class="p">]))</span>
    <span class="k">if</span> <span class="s1">&#39;max-age&#39;</span> <span class="ow">in</span> <span class="n">cc</span><span class="p">:</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">cc</span><span class="p">[</span><span class="s1">&#39;max-age&#39;</span><span class="p">])</span>
        <span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">):</span>
            <span class="k">pass</span></div>


<span class="k">def</span> <span class="nf">set_response_etag</span><span class="p">(</span><span class="n">response</span><span class="p">):</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">streaming</span><span class="p">:</span>
        <span class="n">response</span><span class="p">[</span><span class="s1">&#39;ETag&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">quote_etag</span><span class="p">(</span><span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">())</span>
    <span class="k">return</span> <span class="n">response</span>


<span class="k">def</span> <span class="nf">_precondition_failed</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
        <span class="s1">&#39;Precondition Failed: </span><span class="si">%s</span><span class="s1">&#39;</span><span class="p">,</span> <span class="n">request</span><span class="o">.</span><span class="n">path</span><span class="p">,</span>
        <span class="n">extra</span><span class="o">=</span><span class="p">{</span>
            <span class="s1">&#39;status_code&#39;</span><span class="p">:</span> <span class="mi">412</span><span class="p">,</span>
            <span class="s1">&#39;request&#39;</span><span class="p">:</span> <span class="n">request</span><span class="p">,</span>
        <span class="p">},</span>
    <span class="p">)</span>
    <span class="k">return</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="mi">412</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">_not_modified</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">response</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
    <span class="n">new_response</span> <span class="o">=</span> <span class="n">HttpResponseNotModified</span><span class="p">()</span>
    <span class="k">if</span> <span class="n">response</span><span class="p">:</span>
        <span class="c1"># Preserve the headers required by Section 4.1 of RFC 7232, as well as</span>
        <span class="c1"># Last-Modified.</span>
        <span class="k">for</span> <span class="n">header</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">&#39;Cache-Control&#39;</span><span class="p">,</span> <span class="s1">&#39;Content-Location&#39;</span><span class="p">,</span> <span class="s1">&#39;Date&#39;</span><span class="p">,</span> <span class="s1">&#39;ETag&#39;</span><span class="p">,</span> <span class="s1">&#39;Expires&#39;</span><span class="p">,</span> <span class="s1">&#39;Last-Modified&#39;</span><span class="p">,</span> <span class="s1">&#39;Vary&#39;</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">header</span> <span class="ow">in</span> <span class="n">response</span><span class="p">:</span>
                <span class="n">new_response</span><span class="p">[</span><span class="n">header</span><span class="p">]</span> <span class="o">=</span> <span class="n">response</span><span class="p">[</span><span class="n">header</span><span class="p">]</span>

        <span class="c1"># Preserve cookies as per the cookie specification: &quot;If a proxy server</span>
        <span class="c1"># receives a response which contains a Set-cookie header, it should</span>
        <span class="c1"># propagate the Set-cookie header to the client, regardless of whether</span>
        <span class="c1"># the response was 304 (Not Modified) or 200 (OK).</span>
        <span class="c1"># https://curl.haxx.se/rfc/cookie_spec.html</span>
        <span class="n">new_response</span><span class="o">.</span><span class="n">cookies</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">cookies</span>
    <span class="k">return</span> <span class="n">new_response</span>


<span class="k">def</span> <span class="nf">get_conditional_response</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">etag</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">last_modified</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">response</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
    <span class="c1"># Only return conditional responses on successful requests.</span>
    <span class="k">if</span> <span class="n">response</span> <span class="ow">and</span> <span class="ow">not</span> <span class="p">(</span><span class="mi">200</span> <span class="o">&lt;=</span> <span class="n">response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">&lt;</span> <span class="mi">300</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">response</span>

    <span class="c1"># Get HTTP request headers.</span>
    <span class="n">if_match_etags</span> <span class="o">=</span> <span class="n">parse_etags</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">META</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;HTTP_IF_MATCH&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">))</span>
    <span class="n">if_unmodified_since</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">META</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;HTTP_IF_UNMODIFIED_SINCE&#39;</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">if_unmodified_since</span><span class="p">:</span>
        <span class="n">if_unmodified_since</span> <span class="o">=</span> <span class="n">parse_http_date_safe</span><span class="p">(</span><span class="n">if_unmodified_since</span><span class="p">)</span>
    <span class="n">if_none_match_etags</span> <span class="o">=</span> <span class="n">parse_etags</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">META</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;HTTP_IF_NONE_MATCH&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">))</span>
    <span class="n">if_modified_since</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">META</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;HTTP_IF_MODIFIED_SINCE&#39;</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">if_modified_since</span><span class="p">:</span>
        <span class="n">if_modified_since</span> <span class="o">=</span> <span class="n">parse_http_date_safe</span><span class="p">(</span><span class="n">if_modified_since</span><span class="p">)</span>

    <span class="c1"># Step 1 of section 6 of RFC 7232: Test the If-Match precondition.</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">if_match_etags</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">_if_match_passes</span><span class="p">(</span><span class="n">etag</span><span class="p">,</span> <span class="n">if_match_etags</span><span class="p">)):</span>
        <span class="k">return</span> <span class="n">_precondition_failed</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>

    <span class="c1"># Step 2: Test the If-Unmodified-Since precondition.</span>
    <span class="k">if</span> <span class="p">(</span><span class="ow">not</span> <span class="n">if_match_etags</span> <span class="ow">and</span> <span class="n">if_unmodified_since</span> <span class="ow">and</span>
            <span class="ow">not</span> <span class="n">_if_unmodified_since_passes</span><span class="p">(</span><span class="n">last_modified</span><span class="p">,</span> <span class="n">if_unmodified_since</span><span class="p">)):</span>
        <span class="k">return</span> <span class="n">_precondition_failed</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>

    <span class="c1"># Step 3: Test the If-None-Match precondition.</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">if_none_match_etags</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">_if_none_match_passes</span><span class="p">(</span><span class="n">etag</span><span class="p">,</span> <span class="n">if_none_match_etags</span><span class="p">)):</span>
        <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">method</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">&#39;GET&#39;</span><span class="p">,</span> <span class="s1">&#39;HEAD&#39;</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">_not_modified</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">_precondition_failed</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>

    <span class="c1"># Step 4: Test the If-Modified-Since precondition.</span>
    <span class="k">if</span> <span class="p">(</span><span class="ow">not</span> <span class="n">if_none_match_etags</span> <span class="ow">and</span> <span class="n">if_modified_since</span> <span class="ow">and</span>
            <span class="ow">not</span> <span class="n">_if_modified_since_passes</span><span class="p">(</span><span class="n">last_modified</span><span class="p">,</span> <span class="n">if_modified_since</span><span class="p">)):</span>
        <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">method</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">&#39;GET&#39;</span><span class="p">,</span> <span class="s1">&#39;HEAD&#39;</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">_not_modified</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

    <span class="c1"># Step 5: Test the If-Range precondition (not supported).</span>
    <span class="c1"># Step 6: Return original response since there isn&#39;t a conditional response.</span>
    <span class="k">return</span> <span class="n">response</span>


<span class="k">def</span> <span class="nf">_if_match_passes</span><span class="p">(</span><span class="n">target_etag</span><span class="p">,</span> <span class="n">etags</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Test the If-Match comparison as defined in section 3.1 of RFC 7232.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">target_etag</span><span class="p">:</span>
        <span class="c1"># If there isn&#39;t an ETag, then there can&#39;t be a match.</span>
        <span class="k">return</span> <span class="kc">False</span>
    <span class="k">elif</span> <span class="n">etags</span> <span class="o">==</span> <span class="p">[</span><span class="s1">&#39;*&#39;</span><span class="p">]:</span>
        <span class="c1"># The existence of an ETag means that there is &quot;a current</span>
        <span class="c1"># representation for the target resource&quot;, even if the ETag is weak,</span>
        <span class="c1"># so there is a match to &#39;*&#39;.</span>
        <span class="k">return</span> <span class="kc">True</span>
    <span class="k">elif</span> <span class="n">target_etag</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;W/&#39;</span><span class="p">):</span>
        <span class="c1"># A weak ETag can never strongly match another ETag.</span>
        <span class="k">return</span> <span class="kc">False</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="c1"># Since the ETag is strong, this will only return True if there&#39;s a</span>
        <span class="c1"># strong match.</span>
        <span class="k">return</span> <span class="n">target_etag</span> <span class="ow">in</span> <span class="n">etags</span>


<span class="k">def</span> <span class="nf">_if_unmodified_since_passes</span><span class="p">(</span><span class="n">last_modified</span><span class="p">,</span> <span class="n">if_unmodified_since</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Test the If-Unmodified-Since comparison as defined in section 3.4 of</span>
<span class="sd">    RFC 7232.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">return</span> <span class="n">last_modified</span> <span class="ow">and</span> <span class="n">last_modified</span> <span class="o">&lt;=</span> <span class="n">if_unmodified_since</span>


<span class="k">def</span> <span class="nf">_if_none_match_passes</span><span class="p">(</span><span class="n">target_etag</span><span class="p">,</span> <span class="n">etags</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Test the If-None-Match comparison as defined in section 3.2 of RFC 7232.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">target_etag</span><span class="p">:</span>
        <span class="c1"># If there isn&#39;t an ETag, then there isn&#39;t a match.</span>
        <span class="k">return</span> <span class="kc">True</span>
    <span class="k">elif</span> <span class="n">etags</span> <span class="o">==</span> <span class="p">[</span><span class="s1">&#39;*&#39;</span><span class="p">]:</span>
        <span class="c1"># The existence of an ETag means that there is &quot;a current</span>
        <span class="c1"># representation for the target resource&quot;, so there is a match to &#39;*&#39;.</span>
        <span class="k">return</span> <span class="kc">False</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="c1"># The comparison should be weak, so look for a match after stripping</span>
        <span class="c1"># off any weak indicators.</span>
        <span class="n">target_etag</span> <span class="o">=</span> <span class="n">target_etag</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s1">&#39;W/&#39;</span><span class="p">)</span>
        <span class="n">etags</span> <span class="o">=</span> <span class="p">(</span><span class="n">etag</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s1">&#39;W/&#39;</span><span class="p">)</span> <span class="k">for</span> <span class="n">etag</span> <span class="ow">in</span> <span class="n">etags</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">target_etag</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">etags</span>


<span class="k">def</span> <span class="nf">_if_modified_since_passes</span><span class="p">(</span><span class="n">last_modified</span><span class="p">,</span> <span class="n">if_modified_since</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Test the If-Modified-Since comparison as defined in section 3.3 of RFC 7232.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">return</span> <span class="ow">not</span> <span class="n">last_modified</span> <span class="ow">or</span> <span class="n">last_modified</span> <span class="o">&gt;</span> <span class="n">if_modified_since</span>


<div class="viewcode-block" id="patch_response_headers"><a class="viewcode-back" href="../../../ref/utils.html#django.utils.cache.patch_response_headers">[docs]</a><span class="k">def</span> <span class="nf">patch_response_headers</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">cache_timeout</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Add HTTP caching headers to the given HttpResponse: Expires and</span>
<span class="sd">    Cache-Control.</span>

<span class="sd">    Each header is only added if it isn&#39;t already set.</span>

<span class="sd">    cache_timeout is in seconds. The CACHE_MIDDLEWARE_SECONDS setting is used</span>
<span class="sd">    by default.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">cache_timeout</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">cache_timeout</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">CACHE_MIDDLEWARE_SECONDS</span>
    <span class="k">if</span> <span class="n">cache_timeout</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">cache_timeout</span> <span class="o">=</span> <span class="mi">0</span>  <span class="c1"># Can&#39;t have max-age negative</span>
    <span class="k">if</span> <span class="n">settings</span><span class="o">.</span><span class="n">USE_ETAGS</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">has_header</span><span class="p">(</span><span class="s1">&#39;ETag&#39;</span><span class="p">):</span>
        <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
            <span class="s2">&quot;The USE_ETAGS setting is deprecated in favor of &quot;</span>
            <span class="s2">&quot;ConditionalGetMiddleware which sets the ETag regardless of the &quot;</span>
            <span class="s2">&quot;setting. patch_response_headers() won&#39;t do ETag processing in &quot;</span>
            <span class="s2">&quot;Django 2.1.&quot;</span><span class="p">,</span>
            <span class="n">RemovedInDjango21Warning</span>
        <span class="p">)</span>
        <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="s1">&#39;render&#39;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">callable</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">render</span><span class="p">):</span>
            <span class="n">response</span><span class="o">.</span><span class="n">add_post_render_callback</span><span class="p">(</span><span class="n">set_response_etag</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">response</span> <span class="o">=</span> <span class="n">set_response_etag</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">has_header</span><span class="p">(</span><span class="s1">&#39;Expires&#39;</span><span class="p">):</span>
        <span class="n">response</span><span class="p">[</span><span class="s1">&#39;Expires&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">http_date</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">+</span> <span class="n">cache_timeout</span><span class="p">)</span>
    <span class="n">patch_cache_control</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">max_age</span><span class="o">=</span><span class="n">cache_timeout</span><span class="p">)</span></div>


<div class="viewcode-block" id="add_never_cache_headers"><a class="viewcode-back" href="../../../ref/utils.html#django.utils.cache.add_never_cache_headers">[docs]</a><span class="k">def</span> <span class="nf">add_never_cache_headers</span><span class="p">(</span><span class="n">response</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Adds headers to a response to indicate that a page should never be cached.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">patch_response_headers</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">cache_timeout</span><span class="o">=-</span><span class="mi">1</span><span class="p">)</span>
    <span class="n">patch_cache_control</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">no_cache</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">no_store</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">must_revalidate</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></div>


<div class="viewcode-block" id="patch_vary_headers"><a class="viewcode-back" href="../../../ref/utils.html#django.utils.cache.patch_vary_headers">[docs]</a><span class="k">def</span> <span class="nf">patch_vary_headers</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">newheaders</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Adds (or updates) the &quot;Vary&quot; header in the given HttpResponse object.</span>
<span class="sd">    newheaders is a list of header names that should be in &quot;Vary&quot;. Existing</span>
<span class="sd">    headers in &quot;Vary&quot; aren&#39;t removed.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="c1"># Note that we need to keep the original order intact, because cache</span>
    <span class="c1"># implementations may rely on the order of the Vary contents in, say,</span>
    <span class="c1"># computing an MD5 hash.</span>
    <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">has_header</span><span class="p">(</span><span class="s1">&#39;Vary&#39;</span><span class="p">):</span>
        <span class="n">vary_headers</span> <span class="o">=</span> <span class="n">cc_delim_re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">response</span><span class="p">[</span><span class="s1">&#39;Vary&#39;</span><span class="p">])</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">vary_headers</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="c1"># Use .lower() here so we treat headers as case-insensitive.</span>
    <span class="n">existing_headers</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">header</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="k">for</span> <span class="n">header</span> <span class="ow">in</span> <span class="n">vary_headers</span><span class="p">)</span>
    <span class="n">additional_headers</span> <span class="o">=</span> <span class="p">[</span><span class="n">newheader</span> <span class="k">for</span> <span class="n">newheader</span> <span class="ow">in</span> <span class="n">newheaders</span>
                          <span class="k">if</span> <span class="n">newheader</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">existing_headers</span><span class="p">]</span>
    <span class="n">response</span><span class="p">[</span><span class="s1">&#39;Vary&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">vary_headers</span> <span class="o">+</span> <span class="n">additional_headers</span><span class="p">)</span></div>


<span class="k">def</span> <span class="nf">has_vary_header</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">header_query</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Checks to see if the response has a given header name in its Vary header.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">has_header</span><span class="p">(</span><span class="s1">&#39;Vary&#39;</span><span class="p">):</span>
        <span class="k">return</span> <span class="kc">False</span>
    <span class="n">vary_headers</span> <span class="o">=</span> <span class="n">cc_delim_re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">response</span><span class="p">[</span><span class="s1">&#39;Vary&#39;</span><span class="p">])</span>
    <span class="n">existing_headers</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">header</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="k">for</span> <span class="n">header</span> <span class="ow">in</span> <span class="n">vary_headers</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">header_query</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="n">existing_headers</span>


<span class="k">def</span> <span class="nf">_i18n_cache_key_suffix</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">cache_key</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;If necessary, adds the current locale or time zone to the cache key.&quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">settings</span><span class="o">.</span><span class="n">USE_I18N</span> <span class="ow">or</span> <span class="n">settings</span><span class="o">.</span><span class="n">USE_L10N</span><span class="p">:</span>
        <span class="c1"># first check if LocaleMiddleware or another middleware added</span>
        <span class="c1"># LANGUAGE_CODE to request, then fall back to the active language</span>
        <span class="c1"># which in turn can also fall back to settings.LANGUAGE_CODE</span>
        <span class="n">cache_key</span> <span class="o">+=</span> <span class="s1">&#39;.</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="s1">&#39;LANGUAGE_CODE&#39;</span><span class="p">,</span> <span class="n">get_language</span><span class="p">())</span>
    <span class="k">if</span> <span class="n">settings</span><span class="o">.</span><span class="n">USE_TZ</span><span class="p">:</span>
        <span class="c1"># The datetime module doesn&#39;t restrict the output of tzname().</span>
        <span class="c1"># Windows is known to use non-standard, locale-dependent names.</span>
        <span class="c1"># User-defined tzinfo classes may return absolutely anything.</span>
        <span class="c1"># Hence this paranoid conversion to create a valid cache key.</span>
        <span class="n">tz_name</span> <span class="o">=</span> <span class="n">force_text</span><span class="p">(</span><span class="n">get_current_timezone_name</span><span class="p">(),</span> <span class="n">errors</span><span class="o">=</span><span class="s1">&#39;ignore&#39;</span><span class="p">)</span>
        <span class="n">cache_key</span> <span class="o">+=</span> <span class="s1">&#39;.</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">tz_name</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">,</span> <span class="s1">&#39;ignore&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">,</span> <span class="s1">&#39;_&#39;</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">cache_key</span>


<span class="k">def</span> <span class="nf">_generate_cache_key</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">headerlist</span><span class="p">,</span> <span class="n">key_prefix</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Returns a cache key from the headers given in the header list.&quot;&quot;&quot;</span>
    <span class="n">ctx</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">()</span>
    <span class="k">for</span> <span class="n">header</span> <span class="ow">in</span> <span class="n">headerlist</span><span class="p">:</span>
        <span class="n">value</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">META</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">header</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">value</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
            <span class="n">ctx</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">force_bytes</span><span class="p">(</span><span class="n">value</span><span class="p">))</span>
    <span class="n">url</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">(</span><span class="n">force_bytes</span><span class="p">(</span><span class="n">iri_to_uri</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">build_absolute_uri</span><span class="p">())))</span>
    <span class="n">cache_key</span> <span class="o">=</span> <span class="s1">&#39;views.decorators.cache.cache_page.</span><span class="si">%s</span><span class="s1">.</span><span class="si">%s</span><span class="s1">.</span><span class="si">%s</span><span class="s1">.</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span>
        <span class="n">key_prefix</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">url</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">(),</span> <span class="n">ctx</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">())</span>
    <span class="k">return</span> <span class="n">_i18n_cache_key_suffix</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">cache_key</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">_generate_cache_header_key</span><span class="p">(</span><span class="n">key_prefix</span><span class="p">,</span> <span class="n">request</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Returns a cache key for the header cache.&quot;&quot;&quot;</span>
    <span class="n">url</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">(</span><span class="n">force_bytes</span><span class="p">(</span><span class="n">iri_to_uri</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">build_absolute_uri</span><span class="p">())))</span>
    <span class="n">cache_key</span> <span class="o">=</span> <span class="s1">&#39;views.decorators.cache.cache_header.</span><span class="si">%s</span><span class="s1">.</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span>
        <span class="n">key_prefix</span><span class="p">,</span> <span class="n">url</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">())</span>
    <span class="k">return</span> <span class="n">_i18n_cache_key_suffix</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">cache_key</span><span class="p">)</span>


<div class="viewcode-block" id="get_cache_key"><a class="viewcode-back" href="../../../ref/utils.html#django.utils.cache.get_cache_key">[docs]</a><span class="k">def</span> <span class="nf">get_cache_key</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">key_prefix</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s1">&#39;GET&#39;</span><span class="p">,</span> <span class="n">cache</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Returns a cache key based on the request URL and query. It can be used</span>
<span class="sd">    in the request phase because it pulls the list of headers to take into</span>
<span class="sd">    account from the global URL registry and uses those to build a cache key</span>
<span class="sd">    to check against.</span>

<span class="sd">    If there is no headerlist stored, the page needs to be rebuilt, so this</span>
<span class="sd">    function returns None.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">key_prefix</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">key_prefix</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">CACHE_MIDDLEWARE_KEY_PREFIX</span>
    <span class="n">cache_key</span> <span class="o">=</span> <span class="n">_generate_cache_header_key</span><span class="p">(</span><span class="n">key_prefix</span><span class="p">,</span> <span class="n">request</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">cache</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">cache</span> <span class="o">=</span> <span class="n">caches</span><span class="p">[</span><span class="n">settings</span><span class="o">.</span><span class="n">CACHE_MIDDLEWARE_ALIAS</span><span class="p">]</span>
    <span class="n">headerlist</span> <span class="o">=</span> <span class="n">cache</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">cache_key</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">headerlist</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">_generate_cache_key</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">headerlist</span><span class="p">,</span> <span class="n">key_prefix</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="kc">None</span></div>


<div class="viewcode-block" id="learn_cache_key"><a class="viewcode-back" href="../../../ref/utils.html#django.utils.cache.learn_cache_key">[docs]</a><span class="k">def</span> <span class="nf">learn_cache_key</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">response</span><span class="p">,</span> <span class="n">cache_timeout</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">key_prefix</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">cache</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Learns what headers to take into account for some request URL from the</span>
<span class="sd">    response object. It stores those headers in a global URL registry so that</span>
<span class="sd">    later access to that URL will know what headers to take into account</span>
<span class="sd">    without building the response object itself. The headers are named in the</span>
<span class="sd">    Vary header of the response, but we want to prevent response generation.</span>

<span class="sd">    The list of headers to use for cache key generation is stored in the same</span>
<span class="sd">    cache as the pages themselves. If the cache ages some data out of the</span>
<span class="sd">    cache, this just means that we have to build the response once to get at</span>
<span class="sd">    the Vary header and so at the list of headers to use for the cache key.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">key_prefix</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">key_prefix</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">CACHE_MIDDLEWARE_KEY_PREFIX</span>
    <span class="k">if</span> <span class="n">cache_timeout</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">cache_timeout</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">CACHE_MIDDLEWARE_SECONDS</span>
    <span class="n">cache_key</span> <span class="o">=</span> <span class="n">_generate_cache_header_key</span><span class="p">(</span><span class="n">key_prefix</span><span class="p">,</span> <span class="n">request</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">cache</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">cache</span> <span class="o">=</span> <span class="n">caches</span><span class="p">[</span><span class="n">settings</span><span class="o">.</span><span class="n">CACHE_MIDDLEWARE_ALIAS</span><span class="p">]</span>
    <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">has_header</span><span class="p">(</span><span class="s1">&#39;Vary&#39;</span><span class="p">):</span>
        <span class="n">is_accept_language_redundant</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">USE_I18N</span> <span class="ow">or</span> <span class="n">settings</span><span class="o">.</span><span class="n">USE_L10N</span>
        <span class="c1"># If i18n or l10n are used, the generated cache key will be suffixed</span>
        <span class="c1"># with the current locale. Adding the raw value of Accept-Language is</span>
        <span class="c1"># redundant in that case and would result in storing the same content</span>
        <span class="c1"># under multiple keys in the cache. See #18191 for details.</span>
        <span class="n">headerlist</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">header</span> <span class="ow">in</span> <span class="n">cc_delim_re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">response</span><span class="p">[</span><span class="s1">&#39;Vary&#39;</span><span class="p">]):</span>
            <span class="n">header</span> <span class="o">=</span> <span class="n">header</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">&#39;-&#39;</span><span class="p">,</span> <span class="s1">&#39;_&#39;</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">header</span> <span class="o">==</span> <span class="s1">&#39;ACCEPT_LANGUAGE&#39;</span> <span class="ow">and</span> <span class="n">is_accept_language_redundant</span><span class="p">:</span>
                <span class="k">continue</span>
            <span class="n">headerlist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;HTTP_&#39;</span> <span class="o">+</span> <span class="n">header</span><span class="p">)</span>
        <span class="n">headerlist</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
        <span class="n">cache</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">cache_key</span><span class="p">,</span> <span class="n">headerlist</span><span class="p">,</span> <span class="n">cache_timeout</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">_generate_cache_key</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">request</span><span class="o">.</span><span class="n">method</span><span class="p">,</span> <span class="n">headerlist</span><span class="p">,</span> <span class="n">key_prefix</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="c1"># if there is no Vary header, we still need a cache key</span>
        <span class="c1"># for the request.build_absolute_uri()</span>
        <span class="n">cache</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">cache_key</span><span class="p">,</span> <span class="p">[],</span> <span class="n">cache_timeout</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">_generate_cache_key</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">request</span><span class="o">.</span><span class="n">method</span><span class="p">,</span> <span class="p">[],</span> <span class="n">key_prefix</span><span class="p">)</span></div>


<span class="k">def</span> <span class="nf">_to_tuple</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
    <span class="n">t</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;=&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">t</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
    <span class="k">return</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> <span class="kc">True</span>
</pre></div>

          </div>
        </div>
      </div>
      
        
          <div class="yui-b" id="sidebar">
            
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none" role="search">
  <h3>Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="../../../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    </div>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
              <h3>Last update:</h3>
              <p class="topless">Jun 03, 2019</p>
          </div>
        
      
    </div>

    <div id="ft">
      <div class="nav">
    <a href="../../index.html" title="Module code" accesskey="U">up</a></div>
    </div>
  </div>

      <div class="clearer"></div>
    </div>
  </body>
</html>